<!DOCTYPE html>
<html>

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>复选框（checkbox）全选/全不选/返选</title>
  <style>
    body,
    dl,
    dt,
    dd,
    p {
      margin: 0;
      padding: 0;
    }

    body {
      font-family: Tahoma;
      font-size: 12px;
    }

    label,
    input,
    a {
      vertical-align: middle;
    }

    label {
      padding: 0 10px 0 5px;
    }

    a {
      color: #09f;
      text-decoration: none;
    }

    a:hover {
      color: red;
    }

    dl {
      width: 120px;
      margin: 10px auto;
      padding: 10px 5px;
      border: 1px solid #666;
      border-radius: 5px;
      background: #fafafa;
    }

    dt {
      padding-bottom: 10px;
      border-bottom: 1px solid #666;
    }

    dt label {
      font-weight: 700;
    }

    p {
      margin-top: 10px;
    }
  </style>
</head>

<body>
  <div id="app">
    <dl>
      <dt>
        <input type="checkbox" id="checkAll" v-model="isAllSelected" />
        <label>{{isAllSelected ? '全不选' : '全选'}}</label>
        <a href="" @click.prevent="inverse">反选</a>
      </dt>
      <dd>
        <p v-for="item in selectionsOpt" :key="item.value+item.text">
          <input type="checkbox" name="item" :value="item.value" v-model="selections" />
          <label>{{item.text}}</label>
        </p>

      </dd>
    </dl>
    <center>1、切换全选/全不选文字；2、根据选中个数更新全选框状态；</center>
  </div>
  <script src="./js/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        selections:[],
        selectionsOpt: [
          {
            value: 'a',
            text: '选项（一）'
          },
          {
            value: 'b',
            text: '选项（二）'
          },
          {
            value: 'c',
            text: '选项（三）'
          },
          {
            value: 'd',
            text: '选项（四）'
          }
        ]
      },
      computed: {
        //所有元素选中的状态
        allselections() {
          return this.selectionsOpt.map(item => item.value)
        },
        isAllSelected: {
          get() {
            return this.selections.length == this.allselections.length
          },
          set(val) {
            if (val) {
              this.selections = this.allselections.slice()
            } else {
              this.selections = []
            }
          }
        }
      },
      methods: {
        inverse() {
          let res = this.allselections.filter((item, index) => {
            return !this.selections.includes(item)
          })
          this.selections = res
        }
      }
    })
  </script>
</body>

</html>